#include <linux/segment.h>

EBX     = 0x00
ECX     = 0x04
EDX     = 0x08
ESI     = 0x0C
EDI     = 0x10
EBP     = 0x14
EAX     = 0x18
DS      = 0x1C
ES      = 0x20
FS      = 0x24
GS      = 0x28
ORIG_EAX= 0x2C
EIP     = 0x30
CS      = 0x34
EFLAGS  = 0x38
OLDESP  = 0x3C
OLDSS   = 0x40

.globl divide_error, debug, nmi, int3, overflow, bounds, invalid_op
.globl double_fault, coprocessor_segment_overrun
.globl invalid_TSS, segment_not_present, stack_segment
.globl general_protection, reserved
.globl alignment_check

#define RESTORE_ALL \
    popl %ebx;  \
    popl %ecx;  \
    popl %edx;  \
    popl %esi;  \
    popl %edi;  \
    popl %ebp;  \
    popl %eax;  \
    pop %ds;    \
    pop %es;    \
    pop %fs;    \
    pop %gs;    \
    addl $4, %esp;  \
    iret

.align 4,0x90
ret_from_sys_call:
    RESTORE_ALL

.align 4
divide_error:
    pushl $0        # no error code
    pushl $do_divide_error
.align 4, 0x90
error_code:
    push %fs
    push %es
    push %ds
    pushl %eax
    pushl %ebp
    pushl %edi
    pushl %esi
    pushl %edx
    pushl %ecx
    pushl %ebx
    cld
    movl $-1, %eax
    xchgl %eax, ORIG_EAX(%esp)  # orig_eax (get the error code. )
    xorl %ebx, %ebx         # zero ebx
    mov %gs, %bx            # get the lower order bits of gs
    xchgl %ebx, GS(%esp)    # get the address and save gs.
    pushl %eax              # push the error code
    lea 4(%esp), %edx
    pushl %edx
    movl $(KERNEL_DS), %edx
    mov %dx, %ds
    mov %dx, %es
    call *%ebx
    addl $8, %esp
    jmp ret_from_sys_call

.align 4
debug:
    pushl $0
    pushl $do_debug
    jmp error_code

.align 4
nmi:
    pushl $0
    pushl $do_nmi
    jmp error_code

.align 4
int3:
    pushl $0
    pushl $do_int3
    jmp error_code

.align 4
overflow:
    pushl $0
    pushl $do_overflow
    jmp error_code

.align 4
bounds:
    pushl $0
    pushl $do_bounds
    jmp error_code

.align 4
invalid_op:
    pushl $0
    pushl $do_invalid_op
    jmp error_code

.align 4
coprocessor_segment_overrun:
    pushl $0
    pushl $do_coprocessor_segment_overrun
    jmp error_code

.align 4
reserved:
    pushl $0
    pushl $do_reserved
    jmp error_code

.align 4
double_fault:
    pushl $do_double_fault
    jmp error_code

.align 4
invalid_TSS:
    pushl $do_invalid_TSS
    jmp error_code

.align 4
segment_not_present:
    pushl $do_segment_not_present
    jmp error_code

.align 4
stack_segment:
    pushl $do_stack_segment
    jmp error_code

.align 4
general_protection:
    pushl $do_general_protection
    jmp error_code

.align 4
alignment_check:
    pushl $do_alignment_check
    jmp error_code
